package com.robertux.leaderboard.util.gestoresModelos;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.apache.log4j.Logger;

import com.robertux.leaderboard.beans.EstadoEntidad;
import com.robertux.leaderboard.beans.entities.GrupoProducto;
import com.robertux.leaderboard.beans.entities.Meta;
import com.robertux.leaderboard.beans.entities.ProgresoMeta;
import com.robertux.leaderboard.beans.entities.Usuario;

public class GestorMetas {
	private GestorEntidades<Meta> gMeta;
	private Logger logger;
	
	public GestorMetas() {
		this.gMeta = new GestorEntidades<Meta>();
		this.logger = Logger.getLogger(this.getClass());
	}
	
	public GestorMetas(GestorEntidades<Meta> gestor) {
		this.gMeta = gestor;
		this.logger = Logger.getLogger(this.getClass());
	}
	
	public List<Meta> getMetas() {
		TypedQuery<Meta> qry = this.gMeta.getEntityManager().createQuery("SELECT m FROM Meta m WHERE m.estado = :estado AND m.usuario.estado = :estado", Meta.class);
		qry.setParameter("estado", EstadoEntidad.ACTIVO.getCodigo());
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar las metas: " + e.getMessage(), e);
			return new ArrayList<Meta>();
		}
	}
	
	public List<Meta> getMetas(EstadoEntidad estado) {
		TypedQuery<Meta> qry = this.gMeta.getEntityManager().createQuery("SELECT m FROM Meta m WHERE m.estado = :estado AND m.usuario.estado = :estado", Meta.class);
		qry.setParameter("estado", estado.getCodigo());
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar las metas: " + e.getMessage(), e);
			return new ArrayList<Meta>();
		}
	}
	
	public List<Meta> getMetas(int pagina, int filasPorPagina, String filtro) {
		TypedQuery<Meta> qry = this.gMeta.getEntityManager().createQuery("SELECT m FROM Meta m WHERE m.estado = :estado AND m.usuario.estado = :estado" 
				+ (filtro != null && filtro.trim().length() > 0? " AND (UPPER(m.nombre) LIKE UPPER(:filtro) OR UPPER(m.usuario.usuario) LIKE UPPER(:filtro) OR UPPER(m.usuario.nombre) LIKE UPPER(:filtro))": ""), Meta.class);
		qry.setParameter("estado", EstadoEntidad.ACTIVO.getCodigo());
		
		if(filtro != null && filtro.trim().length() > 0) {
			qry.setParameter("filtro", "%" + filtro + "%");
		}
		qry.setFirstResult((pagina-1) * filasPorPagina);
		qry.setMaxResults(filasPorPagina);
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar las metas: " + e.getMessage(), e);
			return new ArrayList<Meta>();
		}
	}
	
	public List<Meta> getMetas(int idSucursal) {
		TypedQuery<Meta> qry = this.gMeta.getEntityManager().createQuery("SELECT m FROM Meta m WHERE m.sucursalId = :sucId AND m.estado = :estado AND m.usuario.estado = :estado", Meta.class);
		qry.setParameter("sucId", idSucursal);
		qry.setParameter("estado", EstadoEntidad.ACTIVO.getCodigo());
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar las metas: " + e.getMessage(), e);
			return new ArrayList<Meta>();
		}
	}
	
	public List<Meta> getMetas(int idSucursal, int pagina, int filasPorPagina, String filtro) {
		TypedQuery<Meta> qry = this.gMeta.getEntityManager().createQuery("SELECT m FROM Meta m WHERE m.sucursalId = :sucId AND m.estado = :estado AND m.usuario.estado = :estado"
				+ (filtro != null && filtro.trim().length() > 0? " AND (UPPER(m.nombre) LIKE UPPER(:filtro) OR UPPER(m.usuario.usuario) LIKE UPPER(:filtro) OR UPPER(m.usuario.nombre) LIKE UPPER(:filtro))": ""), Meta.class);
		qry.setParameter("sucId", idSucursal);
		qry.setParameter("estado", EstadoEntidad.ACTIVO.getCodigo());
		
		if(filtro != null && filtro.trim().length() > 0) {
			qry.setParameter("filtro", "%" + filtro + "%");
		}
		qry.setFirstResult((pagina-1) * filasPorPagina);
		qry.setMaxResults(filasPorPagina);
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar las metas: " + e.getMessage(), e);
			return new ArrayList<Meta>();
		}
	}
	
	public long getTotalMetas(String filtro) {
		TypedQuery<Long> qry = this.gMeta.getEntityManager().createQuery("SELECT count(m) FROM Meta m WHERE m.estado = :estado AND m.usuario.estado = :estado"
				+ (filtro != null && filtro.trim().length() > 0? " AND (UPPER(m.nombre) LIKE UPPER(:filtro) OR UPPER(m.usuario.usuario) LIKE UPPER(:filtro) OR UPPER(m.usuario.nombre) LIKE UPPER(:filtro))": "")
				, Long.class);
		qry.setParameter("estado", EstadoEntidad.ACTIVO.getCodigo());
		
		if(filtro != null && filtro.trim().length() > 0) {
			qry.setParameter("filtro", "%" + filtro + "%");
		}
		
		try {
			return qry.getSingleResult();
		} catch (NoResultException nrE) {
			return 0;
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar el total de evaluaciones: " + e.getMessage(), e);
			return 0;
		}
	}
	
	public long getTotalMetas(int idSucursal, String filtro) {
		TypedQuery<Long> qry = this.gMeta.getEntityManager().createQuery("SELECT count(m) FROM Meta m WHERE m.sucursalId = :sucId AND m.estado = :estado AND m.usuario.estado = :estado"
				+ (filtro != null && filtro.trim().length() > 0? " AND (UPPER(m.nombre) LIKE UPPER(:filtro) OR UPPER(m.usuario.usuario) LIKE UPPER(:filtro) OR UPPER(m.usuario.nombre) LIKE UPPER(:filtro))": "")
				, Long.class);
		qry.setParameter("estado", EstadoEntidad.ACTIVO.getCodigo());
		qry.setParameter("sucId", idSucursal);
		
		if(filtro != null && filtro.trim().length() > 0) {
			qry.setParameter("filtro", "%" + filtro + "%");
		}
		
		try {
			return qry.getSingleResult();
		} catch (NoResultException nrE) {
			return 0;
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar el total de evaluaciones: " + e.getMessage(), e);
			return 0;
		}
	}
	
	public List<Meta> getMetas(Usuario usr) {
		TypedQuery<Meta> qry = this.gMeta.getEntityManager().createQuery("SELECT m FROM Meta m WHERE m.estado = :estado AND m.usuario.id = :usrId", Meta.class);
		qry.setParameter("estado", EstadoEntidad.ACTIVO.getCodigo());
		qry.setParameter("usrId", usr.getId());
		
		try {
			return qry.getResultList();
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar las metas: " + e.getMessage(), e);
			return new ArrayList<Meta>();
		}
	}
	
	public Meta getMeta(long metaId) {
		return this.gMeta.getEntidad("Meta", Meta.class, metaId);
	}
	
	public Meta getMeta(String nombre) {
		TypedQuery<Meta> qry = this.gMeta.getEntityManager().createQuery("SELECT m FROM Meta m WHERE m.nombre = :nombre", Meta.class);
		qry.setParameter("nombre", nombre);
		
		try {
			return qry.getSingleResult();
		} catch (NoResultException nrE) {
			return null;
		} catch (Exception e) {
			this.logger.error("Error tratando de consultar las metas: " + e.getMessage(), e);
			return null;
		}
	}
	
	public boolean actualizarMeta(Meta meta) {
		try {
			this.gMeta.actualizar(meta);
			return true;
		} catch (Exception e) {
			this.logger.error("Error tratando de actualizar la meta: " + e.getMessage(), e);
			return false;
		}
	}
	
	public boolean eliminarMeta(Meta meta) {
		try {
			meta.setEstado(EstadoEntidad.ELIMINADO.getCodigo());
			this.gMeta.actualizar(meta);
			return true;
		} catch (Exception e) {
			this.logger.error("Error tratando de eliminar la meta: " + e.getMessage(), e);
			return false;
		}
	}
	
	public ProgresoMeta getProgreso(Meta meta, int mes, int anio) {
		for(ProgresoMeta progreso: meta.getProgresoMetas()) {
			Calendar calProgreso = new GregorianCalendar();
			calProgreso.setTime(progreso.getFecha());
			if((calProgreso.get(Calendar.MONTH)+1) == mes && calProgreso.get(Calendar.YEAR) == anio) {
				return progreso;
			}
		}
		return null;
	}
	
	public int getTotalCantidadVentas(GrupoProducto gPrd, Meta meta, Usuario usr) {
		int totalCantidadVentas = 0;
		GestorEntidadesFarmacia gEntFrm = new GestorEntidadesFarmacia();
		totalCantidadVentas += gEntFrm.getTotalCantidadVentasProductos(gPrd, meta, new GestorExclusiones().getExclusiones());
		
		return totalCantidadVentas;
	}
	
	public double getTotalPrecioVentas(GrupoProducto gPrd, Meta meta, Usuario usr) {
		double totalPrecioVentas = 0;
		GestorEntidadesFarmacia gEntFrm = new GestorEntidadesFarmacia();
		totalPrecioVentas += gEntFrm.getTotalPrecioVentasProductos(gPrd, meta, new GestorExclusiones().getExclusiones());
		
		return totalPrecioVentas;
	}
	
	public int cambiarEstadoMetas(EstadoEntidad estadoActual, EstadoEntidad estadoNuevo) {
		int metasModificadas = 0;
		try {
			 
			Query qry = this.gMeta.getEntityManager().createQuery("UPDATE Meta m SET m.estado = :estadoNuevo WHERE m.estado = :estado ");
			qry.setParameter("estadoNuevo", estadoNuevo.getCodigo());
			qry.setParameter("estado", estadoActual.getCodigo());
			
			this.gMeta.getEntityManager().getTransaction().begin();
			metasModificadas = qry.executeUpdate();
			this.gMeta.getEntityManager().getTransaction().commit();
		} catch (Exception e) {
			this.logger.error("Error tratando de actualizar la meta: " + e.getMessage(), e);
		}
		
		return metasModificadas;
	} 
}
